Android Native binder 通信实例 您所在的位置:网站首页 安卓 binder 使用实例 Android Native binder 通信实例

Android Native binder 通信实例

2023-11-25 16:17| 来源: 网络整理| 查看: 265

最近在考虑android native 跨进程通信问题,之前用hidl实现过system进程和vendor进程通信,这次考虑用aidl 在native层实现跨进程通信,了解到binder通信最大发送数据是1MB , 想要测试看看跨进程大数据通信吞吐率能达到多少。 下面开始上代码。

1 定义接口AIDL

首先是定义接口,需要先想好我们需要定义哪些通信接口。把想要提供的接口、callback 定义好,后续通过继承接口类实现具体功能。aidl文件需要以其包名的路径格式放在代码工程目录的:aidl/com/test/speedtest 目录下面:

ISpeedTestService.aidl : 

package com.test.speedtest;    import com.test.speedtest.ISpeedTestCallback;  // 在aidl中使用到其他aidl定义的接口需要import

interface ISpeedTestService {     oneway void startSpeedTest();   // oneway 修饰使得耗时的调用不阻塞当前线程,直接返回     void setSpeedTestCb(ISpeedTestCallback cb); }  

ISpeedTestCallback.aidl:

package com.test.speedtest;    interface ISpeedTestCallback {   oneway void onSpeedTestDone(in float speed);  // callback异步返回测试结果   oneway void onSend(in byte[] buf, int length);   //通过callback接口给client发数据 }

aidl文件在编译时会自动生成源文件,路径在out/target/product/xxx/obj/EXECUTABLES/SpeedTestClient_intermediates/aidl-generated 目录下,里面会有头文件和cpp文件,我们只需要后面继承里面的类重新实现里面的逻辑即可。  

不知道具体路径在哪里可以通过find 命令去查找, 比如: find . -name ISpeedTestService.h

我们只需要继承BnSpeedTestService 和 BnSpeedTestCallback 两个类即可,其他类都用自动生成的,不知道怎么继承自动生成的代码的话需要先找到自动生成代码,然后对着这两个类的实现重写类的实现。

2. 配置Android.mk

aidl文件定义好了后配置Android.mk 文件或者Android.bp, 这里以Android.mk为例:

LOCAL_PATH := $(call my-dir)    include $(CLEAR_VARS)

LOCAL_SHARED_LIBRARIES := libcutils \                           libutils \                           libbinder \      #binder通信so库                           liblog

LOCAL_MODULE :=  SpeedTestService LOCAL_C_INCLUDES := $(LOCAL_PATH)/inc LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/aidl LOCAL_SRC_FILES := $(call all-cpp-files-under, server/src)  #包含service端cpp文件 LOCAL_SRC_FILES += $(call all-subdir-Iaidl-files, aidl)    # 包含所有aidl文件

include $(BUILD_EXECUTABLE)

include $(CLEAR_VARS)

LOCAL_SHARED_LIBRARIES := libcutils \                           libutils \                           libbinder \                           liblog

LOCAL_MODULE :=  SpeedTestClient LOCAL_C_INCLUDES := $(LOCAL_PATH)/inc LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/aidl LOCAL_SRC_FILES := $(call all-cpp-files-under, client/src)  #包含client端cpp文件 LOCAL_SRC_FILES += $(call all-subdir-Iaidl-files, aidl)

include $(BUILD_EXECUTABLE)  

3. 实现Service端代码

SPeedTestService.h:

#ifndef SPEED_TEST_SERVICE_H #define SPEED_TEST_SERVICE_H

#include #include #include #include #include #include #include #include #include #include

#include #include #include #include #include #include #include

#include #include

#include "logUtils.h"

using namespace android; using namespace std; using namespace com::test::speedtest;

namespace com { namespace test { namespace speedtest {     class SpeedTestService : public BnSpeedTestService {         public:         static sp getInstance();         ::android::binder::Status setSpeedTestCb(const ::android::sp& cb);         ::android::binder::Status startSpeedTest();     private:        atomic stoped;        mutex mMutex;        condition_variable finished;        uint32_t count;        sp mCallback;        void startTimer(uint32_t interval);        void startSendThread();         SpeedTestService();         ~SpeedTestService();            }; } // namespace speedtest } // namespace test } // namespace speedtest #endif /* SPEED_TEST_SERVICE_H */

SPeedTestService.cpp:

#include #include "SpeedTestService.h"

#define TAG "SpeedTestService"

using namespace android; using namespace com::test::speedtest;

namespace com { namespace test { namespace speedtest {    ::android::binder::Status  SpeedTestService::startSpeedTest() {        startTimer(10000); // start a 10s timer thread        startSendThread();        std::unique_lock lock(mMutex);        finished.wait(lock);        //counter speed        ALOGD(TAG,"Recived finished cond");        float speed = count*512*8/10240;        mCallback->onSpeedTestDone(speed);        ALOGD(TAG, "send test result %.2f", speed);        return ::android::binder::Status::ok();    }

   SpeedTestService:: SpeedTestService(): stoped(false), mCallback(nullptr), count(0) {

   }    SpeedTestService:: ~SpeedTestService() {            }

   void SpeedTestService:: startTimer(uint32_t interval) {        ALOGD(TAG, "start timer ...");        if( stoped.load() ) {            return;        }        std::thread([this, interval] () {                std::this_thread::sleep_for(std::chrono::milliseconds(interval));                ALOGD(TAG, "sleep timer exited");                stoped.store(true);       }).detach();    }

   void SpeedTestService::startSendThread() {        if(mCallback == nullptr) {            ALOGE(TAG, "callback is nullptr");        return;        }        ALOGD(TAG, "start send thread");        std::thread([=](){            std::vector vec(256*1024,'c');        while(!stoped.load()) {            if(mCallback != nullptr) {                mCallback->onSend(vec, vec.size());                count += 1;            }        }            finished.notify_all();        ALOGD(TAG, "send thread finished");        }).detach();    }

 ::android::binder::Status SpeedTestService::setSpeedTestCb(const      ::android::sp &cb) {        mCallback = cb;        return ::android::binder::Status::ok();    }

   sp SpeedTestService::getInstance() {        return new SpeedTestService();    }

} //namespace speedtest } //namespace test } //namespace com  

main.cpp:

#include "SpeedTestService.h" #include

int main(int argc, char* argv[]) {         sp proc(ProcessState::self());         sp mService = SpeedTestService::getInstance();     if(mService == nullptr) {             ALOGE("SpeedTestService", "failed to new service");     }         status_t ret = defaultServiceManager()->addService(String16("com.test.speedtest.ISpeedTestService"), mService);     ALOGD("SpeedTestService", "add service return %d", ret);         ProcessState::self()->startThreadPool();         IPCThreadState::self()->joinThreadPool();         return 0; }

4. 实现客户端代码

SpeedTestCallback.h:

#ifndef SPEED_TEST_CALLBACK_H #define SPEED_TEST_CALLBACK_H

#include #include #include #include #include

#include #include #include #include #include #include #include

#include #include

#include "logUtils.h"

using namespace android; using namespace std; using namespace com::test::speedtest;

namespace com { namespace test { namespace speedtest {     class SpeedTestCallback : public BnSpeedTestCallback {         public:         static sp getInstance();         virtual ::android::binder::Status onSpeedTestDone(float speed);             virtual ::android::binder::Status onSend(const ::std::vector &buf, int32_t length);     private:            SpeedTestCallback();            ~SpeedTestCallback();            }; } // namespace speedtest } // namespace test } // namespace speedtest

#endif /* SPEED_TEST_CALLBACK_H */

SpeedTestCallback.cpp:

#include "SpeedTestCallback.h" #define TAG "SpeedTestCallback"

namespace com { namespace test { namespace speedtest {

SpeedTestCallback::SpeedTestCallback(){} SpeedTestCallback::~SpeedTestCallback(){}

::android::binder::Status SpeedTestCallback::onSpeedTestDone(float speed) {     ALOGD(TAG, "Bn SpeedTestCallback : onSpeedTestDone %f", speed);         return ::android::binder::Status::ok(); }

::android::binder::Status SpeedTestCallback::onSend(const ::std::vector &buf, int32_t length) {     //ALOGD(TAG, "Bn SpeedTestCallback: received data lenth %d", length);     return ::android::binder::Status::ok(); }

sp SpeedTestCallback::getInstance() {     return new SpeedTestCallback(); } } //namespace speedtest } //namespace test } //namespace com  

main.cpp:

#include "SpeedTestService.h" #include "SpeedTestCallback.h"

using namespace com::test::speedtest;

#define TAG "SpeedTestClient"

sp getService() {     ALOGD(TAG,"get SpeedTestService...");     sp sm = defaultServiceManager();     if(sm == nullptr) {         ALOGE(TAG, "failed to get service manager");     return nullptr;     }     sp binder = sm->getService(String16("com.test.speedtest.ISpeedTestService"));     if(binder == nullptr) {         ALOGE(TAG, "failed to get ISpeedTestService");         return nullptr;     }          sp service = interface_cast(binder);     return service; } int main(int argc, char *argv[]) {     sp proxy = getService();     if(proxy == nullptr){         ALOGE(TAG, "failed get binder service");     }     proxy->setSpeedTestCb(SpeedTestCallback::getInstance());     proxy->startSpeedTest();     IPCThreadState::self()->joinThreadPool();  // 加入如到线程池中不让程序退出     return 0; }

logUtils.h:

#ifndef SPEED_TEST_UTILS_H #define SPEED_TEST_UTILS_H

#include

#define ALOGI(TAG, ...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__) #define ALOGV(TAG, ...) __android_log_print(ANDROID_LOG_VERBOSE,TAG,__VA_ARGS__) #define ALOGD(TAG, ...) __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__) #define ALOGE(TAG, ...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__) #define ALOGW(TAG, ...) __android_log_print(ANDROID_LOG_WARN,TAG,__VA_ARGS__) #define ALOGF(TAG, ...) __android_log_print(ANDROID_LOG_FATAL,TAG,__VA_ARGS__) #endif  

5. 运行结果

编译生成SpeedTestService 和 SpeedTestClient 两个bin文件,push到system/bin目录下,然后关闭sepolicy ,先执行./SpeedTestService , 再开一个终端执行./SpeedTestClient : 

10-28 07:56:45.507  5183  5183 D SpeedTestService: add service return 0 10-28 07:56:52.574  5187  5187 D SpeedTestClient: get SpeedTestService... 10-28 07:56:52.581  5183  5184 D SpeedTestService: start timer ... 10-28 07:56:52.582  5183  5184 D SpeedTestService: start send thread 10-28 07:57:02.583  5183  5188 D SpeedTestService: sleep timer exited 10-28 07:57:02.584  5183  5189 D SpeedTestService: send thread finished 10-28 07:57:02.584  5183  5184 D SpeedTestService: Recived finished cond 10-28 07:57:02.584  5187  5187 D SpeedTestCallback: Bn SpeedTestCallback : onSpeedTestDone 6166.000000 10-28 07:57:02.584  5183  5184 D SpeedTestService: send test result 6166.00



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有